﻿using Quartz;
using Quartz.Impl;
using Quartz.Impl.Matchers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Wexflow.Core
{
    public class QuartzManage
    {
        // 1.构造一个调度程序工厂
        static Task<IScheduler> task_scheduler = StdSchedulerFactory.GetDefaultScheduler();
        static IScheduler scheduler;
        private static readonly object objlock = new object();
        static QuartzManage()
        {
            if (scheduler == null)
            {
                lock (objlock)
                {
                    if (scheduler == null)
                    {
                        // 2. 得到一个调度器
                        scheduler = task_scheduler.Result;
                        scheduler.Start();
                    }
                }
            }
        }

        /// <summary>
        /// 以Simple开始一个工作。只能在时分秒的维度上指定时间间隔。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="name"></param>
        /// <param name="simpleInterval"></param>
        public static void StartJobWithSimple<T>(string name, Action<SimpleScheduleBuilder> simpleInterval) where T : IJob
        {
            IJobDetail job = JobBuilder.Create<T>().WithIdentity(name + "_job", name + "_group").Build();
            ITrigger Simple = TriggerBuilder.Create().StartNow()
                                .WithIdentity(name + "_trigger", name + "_group")
                               .WithSimpleSchedule(simpleInterval)
                               .Build() as ISimpleTrigger;
            scheduler.ScheduleJob(job, Simple);
        }


        /// <summary>
        /// // 以Calendar Interval开始一个工作。扩展了Simplescheduler的功能，可以在分秒天周月年轮询，同时可以排除Trigger中一些特定的时间节点。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="name"></param>
        /// <param name="dateTime"></param>
        public static void StartJobWithCalendar<T>(string name, Action<CalendarIntervalScheduleBuilder> calendarInterval) where T : IJob
        {
            IJobDetail job = JobBuilder.Create<T>().WithIdentity(name + "_job", name + "_group").Build();
            ITrigger Calendar =
                   TriggerBuilder.Create()
                        //.StartAt(DateTimeOffset.Parse("2018/1/6 13:17:00"))
                        .WithIdentity(name + "_trigger", name + "_group")
                        //.WithCalendarIntervalSchedule(x => x.WithIntervalInMonths(1))  //一月执行一次
                        .WithCalendarIntervalSchedule(calendarInterval)
                        .Build();
            scheduler.ScheduleJob(job, Calendar);
        }

        /// <summary>
        /// 以 Daily Time开始一个工作。主要用于指定每周的某几天执行，如我们想让每周的周六周日的8:00-20:00，每两秒执行一次
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="name"></param>
        /// <param name="dailyTimeInterval"></param>
        public static void StartJobWithDailyTime<T>(string name, Action<DailyTimeIntervalScheduleBuilder> dailyTimeInterval) where T : IJob
        {
            IJobDetail job = JobBuilder.Create<T>().WithIdentity(name + "_job", name + "_group").Build();
            ITrigger DailyTime = TriggerBuilder.Create()
                 .WithIdentity(name + "_trigger", name + "_group")
                 //.WithDailyTimeIntervalSchedule(x => x.OnDaysOfTheWeek(new DayOfWeek[] { DayOfWeek.Saturday, DayOfWeek.Sunday }) //周六和周日
                 //                               .StartingDailyAt(TimeOfDay.HourMinuteAndSecondOfDay(8, 00, 00)) //8点开始
                 //                               .EndingDailyAt(TimeOfDay.HourMinuteAndSecondOfDay(20, 00, 00))  //20点结束
                 //                               .WithIntervalInSeconds(2)                                       //两秒执行一次，可设置时分秒维度
                 //                               .WithRepeatCount(3))                                            //一共执行3+1次
                 .WithDailyTimeIntervalSchedule(dailyTimeInterval)
                 .Build();
            scheduler.ScheduleJob(job, DailyTime);
        }

        /// <summary>
        /// 以Cron开始一个工作。通过Cron表达式表示任意的时间节点
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="name"></param>
        /// <param name="CronExpression"></param>
        public static void StartJobWithCron<T>(string name, string CronExpression,Workflow wf=null) where T : IJob
        {
            IJobDetail job = JobBuilder.Create<T>().WithIdentity(name + "_job", name + "_group").Build();
            if (wf != null) {
                job.JobDataMap.Put("workflow", wf);
            }
           
            ITrigger CronTrigger = TriggerBuilder.Create().StartNow().WithIdentity(name + "_trigger", name + "_group")
                                    .WithCronSchedule(CronExpression)
                                    .Build() as ICronTrigger;

            //JobListener监控所有的job
            //scheduler.ListenerManager.AddJobListener(new JobListener(), GroupMatcher<JobKey>.AnyGroup());

            scheduler.ScheduleJob(job, CronTrigger);
        }

        /// <summary>
        /// 修改作业
        /// 这种办法可以根据job名称找到触发器，也可以找到Job，这样就可以在任何地方修改Job频次，不再限于IJob的实现方法Execute内以此实现了：即时修改执行频次即时生效
        /// </summary>
        /// <param name="cronExpression"></param>
        /// <param name="name"></param>
        public static async void ModifyJob(string cronExpression, string name)
        {
            //触发器的key
            TriggerKey triggerKey = new TriggerKey(name + "_trigger", name + "_group");
            ITrigger trigger = await scheduler.GetTrigger(triggerKey);

            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.CronSchedule(cronExpression);
            trigger = trigger.GetTriggerBuilder().WithIdentity(triggerKey).WithSchedule(scheduleBuilder).Build();

            await scheduler.RescheduleJob(triggerKey, trigger);
        }

        /// <summary>
        /// 删除Job，即时删除，不再限于IJob的实现方法Execute内
        /// </summary>
        /// <param name="job"></param>
        /// <param name="trigger"></param>
        public static void DeleteJob(string name)
        {
            //触发器的key
            TriggerKey triggerKey = new TriggerKey(name + "_trigger", name + "_group");
            //Job的Key
            JobKey jobKey = new JobKey(name + "_job", name + "_group");
            scheduler.PauseTrigger(triggerKey);//暂停触发器
            scheduler.UnscheduleJob(triggerKey);//移除触发器
            scheduler.DeleteJob(jobKey);
        }

        /// <summary>
        /// 删除Job
        /// </summary>
        /// <param name="job"></param>
        /// <param name="trigger"></param>
        public static void DeleteJob(IJobDetail job, ITrigger trigger)
        {
            scheduler.PauseTrigger(trigger.Key);//暂停触发器
            scheduler.UnscheduleJob(trigger.Key);//移除触发器
            scheduler.DeleteJob(job.Key);
        }

        /// <summary>
        /// 停止运行
        /// </summary>
        public static void ShutDownJob()
        {
            if (scheduler != null && !scheduler.IsShutdown)
            {
                scheduler.Shutdown();
            }
        }

    }
}
